package com.kanshu.basictest.ui.activity.basic.annotation;

import android.util.Log;
import android.view.View;
import android.widget.AdapterView;

import com.kanshu.basictest.R;
import com.kanshu.basictest.annotation.DialogAnnotation;
import com.kanshu.basictest.annotation.DialogAnnotationTestType;
import com.kanshu.basictest.model.menu.MenuItem;
import com.kanshu.basictest.ui.base.BaseListMenuActivity;

import java.lang.reflect.AccessibleObject;
import java.lang.reflect.AnnotatedElement;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.GenericDeclaration;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;

public class CustomizedAnnotationActivity extends BaseListMenuActivity {

    @Override
    protected String provideBarTitle() {
        return "AndroidBasicTest";
    }

    public static final String TAG = "自定义注解";


    @Override
    protected List<? extends MenuItem> provideMenuData() {
        List<MenuItem> menuItems = new ArrayList<>();
        menuItems.add(0, new MenuItem("getAnnotationProperty", R.color.brown_300));//@Deprecated

        return menuItems;
    }

    @Override
    protected void init() {
        super.init();
    }

    @Override
    public void onItemClick(AdapterView<?> adapterView, View view, int position, long id) {
        switch (position) {
            case 0://@Deprecated
                getAnnotationFromClass();
                break;
            default:
                break;
        }
    }


    /**
     * 注解属性值的读取测试
     * <p>
     * 实现手段:Java 反射技术
     * <p>
     * 涉及到的方法：
     * 1.{@link AnnotatedElement#isAnnotationPresent(Class annotationClass)} :判断类是否使用了annotationClass注解。
     * <p>
     * 2.{@link AnnotatedElement#getAnnotation(Class annotationClass)}  :获取元素上指定类型的注解，若不存在，则返回null。
     * 3.{@link AnnotatedElement#getDeclaredAnnotation(Class annotationClass)}  :Java8新增，获取直接修饰该程序元素的指定类型的注解，若不存在，则返回null。
     * <p>
     * 4.{@link AnnotatedElement#getAnnotations()} :判获取该程序元素上的所有注解
     * 5.{@link AnnotatedElement#getDeclaredAnnotations()}  :Java8新增，获取直接修饰该程序元素的所有注解。
     * <p>
     * 6.{@link AnnotatedElement#getAnnotationsByType(Class annotationClass)}  :该方法的功能与前面介绍的getAnnotation()方法的功能类似。但由于Java8增加了重复注解的功能，
     *     因此需要使用该方法获取修饰该程序元素的指定类型的多个注解。
     * 7.{@link AnnotatedElement#getDeclaredAnnotationsByType(Class annotationClass)}  :该方法的功能与前面介绍的getAnnotation()方法的功能类似。但由于Java8增加了重复注解的功能，
     *     因此需要使用该方法获取直接修饰该程序元素的指定类型的多个注解。
     * <p>
     * <p>
     * 说明：
     * 1.AnnotatedElement接口，提供了一系列关于注解操作的相关方法。
     * 2.实现了AnnotatedElement接口的类有：
     * >>>{@link AccessibleObject}      :The AccessibleObject class is the base class for Field, Method and Constructor objects.
     * >>>{@link Class }            :Instances of the class Class represent classes and interfaces in a running Java application.
     * >>>{@link Constructor}  :Constructor provides information about, and access to, a single constructor for a class.
     * >>>{@link Field }            :A Field provides information about, and dynamic access to, a single field of a class or an interface.
     * >>>{@link GenericDeclaration    }:A common interface for all entities that declare type variables.
     * >>>{@link Method }       :A Method provides information about, and access to, a single method on a class or interface.
     * >>>{@link Package }           :Package objects contain version information about the implementation and specification of a Java package.
     */
    private void getAnnotationFromClass() {

        //判断
        boolean isAnnotationPresent = DialogAnnotationTestType.class.isAnnotationPresent(DialogAnnotation.class);
        Log.i(TAG, "isAnnotationPresent: " + isAnnotationPresent);//true


        //获取DialogAnnotationTestType类上的DialogAnnotation注解对象
        DialogAnnotation dialogAnnotation = DialogAnnotationTestType.class.getAnnotation(DialogAnnotation.class);
        //读取属性值
        boolean flag = dialogAnnotation.flag();//false
        String msg = dialogAnnotation.msg();//true
        //打印类上注解的属性值
        Log.i(TAG, "getAnnotationProperty: flag：" + flag + "---msg:" + msg);


    }

    /**
     * 注解属性值的读取测试
     * <p>
     * 实现手段:Java 反射技术
     * <p>
     * 涉及到的方法：
     * 1.{@link AnnotatedElement#isAnnotationPresent(Class annotationClass)} :判断类是否使用了annotationClass注解。
     * 2.{@link AnnotatedElement#getAnnotation(Class annotationClass)}  :获取元素上指定类型的注解。
     * 3.{@link AnnotatedElement#getAnnotations()} :判获取元素上的所有注解
     * <p>
     * 4.{@link AnnotatedElement#getAnnotationsByType(Class annotationClass)}  :判断类是否使用了annotationClass注解。
     * 5.{@link AnnotatedElement#getDeclaredAnnotation(Class annotationClass)}  :判断类是否使用了annotationClass注解。
     * 6.{@link AnnotatedElement#getDeclaredAnnotations()}  :判断类是否使用了annotationClass注解。
     * 7.{@link AnnotatedElement#getDeclaredAnnotationsByType(Class annotationClass)}  :判断类是否使用了annotationClass注解。
     * <p>
     * <p>
     * 说明：
     * 1.AnnotatedElement接口，提供了一系列关于注解操作的相关方法。
     * 2.实现了AnnotatedElement接口的类有：
     * >>>{@link AccessibleObject}      :The AccessibleObject class is the base class for Field, Method and Constructor objects.
     * >>>{@link Class }            :Instances of the class Class represent classes and interfaces in a running Java application.
     * >>>{@link Constructor}  :Constructor provides information about, and access to, a single constructor for a class.
     * >>>{@link Field }            :A Field provides information about, and dynamic access to, a single field of a class or an interface.
     * >>>{@link GenericDeclaration    }:A common interface for all entities that declare type variables.
     * >>>{@link Method }       :A Method provides information about, and access to, a single method on a class or interface.
     * >>>{@link Package }           :Package objects contain version information about the implementation and specification of a Java package.
     */
    private void getAnnotationFromField() {


        try {
            Field title = DialogAnnotationTestType.class.getDeclaredField("title");
            title.setAccessible(true);

        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        }
    }


}
